added SSCLI 1.0
[windows-sources.git] / shared source / sscli20 / jscript / engine / jslocalfield.cs
blobb6a6efab23427f5c2f91acec4382154fc0e58d43
1 // ==++==
2 //
3 //
4 // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
5 //
6 // The use and distribution terms for this software are contained in the file
7 // named license.txt, which can be found in the root of this distribution.
8 // By using this software in any fashion, you are agreeing to be bound by the
9 // terms of this license.
10 //
11 // You must not remove this notice, or any other, from this software.
12 //
13 //
14 // ==--==
16 namespace Microsoft.JScript {
18 using System;
19 using System.Collections;
20 using System.Globalization;
21 using System.Reflection;
23 public sealed class JSLocalField : JSVariableField{
24 internal int slotNumber;
25 internal IReflect inferred_type; //Records a guess of what the type of the field is. null = unknown.
26 private ArrayList dependents; //A list of other fields whose types have been inferred (guessed) based on the inferred type of this field.
27 //The dependend fields need to have their guesses changed.
28 internal bool debugOn; // whether this local field was in a section of code with debug set or not. Control emitting debug info for the local
29 internal JSLocalField outerField; //If this field is a copy of an outer scope field, the outer scope field is kept in here.
30 internal bool isDefined; //Indicates whether an assignment to the field has been encountered.
31 internal bool isUsedBeforeDefinition;
33 public JSLocalField(String name, RuntimeTypeHandle handle, int slotNumber)
34 : this(name, null, slotNumber, Missing.Value){
35 this.type = new TypeExpression(new ConstantWrapper(Type.GetTypeFromHandle(handle), null));
36 this.isDefined = true;
39 internal JSLocalField(String name, FunctionScope scope, int slotNumber, Object value)
40 : base(name, scope, FieldAttributes.Static|FieldAttributes.Public) {
41 this.slotNumber = slotNumber;
42 this.inferred_type = null;
43 this.dependents = null;
44 this.value = value;
45 this.debugOn = false;
46 this.outerField = null;
47 this.isDefined = false;
48 this.isUsedBeforeDefinition = false;
51 public override Type FieldType{
52 get{
53 if (this.type != null)
54 return base.FieldType;
55 else
56 return Convert.ToType(this.GetInferredType(null));
60 internal override IReflect GetInferredType(JSField inference_target){
61 if (this.outerField != null)
62 return this.outerField.GetInferredType(inference_target);
63 if (this.type != null)
64 return base.GetInferredType(inference_target);
65 if (this.inferred_type == null || this.inferred_type == Typeob.Object)
66 return Typeob.Object;
67 if (inference_target != null && inference_target != this){
68 if (this.dependents == null)
69 this.dependents = new ArrayList();
70 this.dependents.Add(inference_target);
72 return this.inferred_type;
75 public override Object GetValue(Object obj){
76 if ((this.attributeFlags&FieldAttributes.Literal) != (FieldAttributes)0 && !(this.value is FunctionObject))
77 return this.value;
78 else{
79 while (obj is BlockScope) obj = ((BlockScope)obj).GetParent();
80 StackFrame sf = (StackFrame)obj;
81 JSLocalField f = this.outerField;
82 int slot = this.slotNumber;
83 while (f != null){
84 slot = f.slotNumber;
85 sf = (StackFrame)sf.GetParent();
86 f = f.outerField;
88 return sf.localVars[slot];
92 internal void SetInferredType(IReflect ir, AST expr){
93 this.isDefined = true;
94 if (this.type != null)
95 return; //The local variable has a type annotation.
96 if (this.outerField != null){
97 this.outerField.SetInferredType(ir, expr);
98 return;
100 if (Convert.IsPrimitiveNumericTypeFitForDouble(ir))
101 ir = Typeob.Double;
102 else if (ir == Typeob.Void)
103 ir = Typeob.Object;
104 if (this.inferred_type == null)
105 this.inferred_type = ir;
106 else{
107 //Check to see if ir is compatible with this.inferred_type. If not, generalize this.inferred_type to Object and invalidate dependants.
108 if (ir == this.inferred_type) return;
109 if (!Convert.IsPrimitiveNumericType(this.inferred_type) || !Convert.IsPrimitiveNumericType(ir) ||
110 !Convert.IsPromotableTo(ir, this.inferred_type)){
111 this.inferred_type = Typeob.Object;
112 if (this.dependents != null)
113 for (int i = 0, n = this.dependents.Count; i < n; i++)
114 ((JSLocalField)this.dependents[i]).SetInferredType(Typeob.Object, null);
119 public override void SetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, CultureInfo locale){
120 if (this.type != null)
121 value = Convert.Coerce(value, this.type);
122 while (obj is BlockScope) obj = ((BlockScope)obj).GetParent();
123 StackFrame sf = (StackFrame)obj;
124 JSLocalField f = this.outerField;
125 int slot = this.slotNumber;
126 while (f != null){
127 slot = f.slotNumber;
128 sf = (StackFrame)sf.GetParent();
129 f = f.outerField;
131 if (sf.localVars == null) return; //happens when assigning to a constant from latebound code
132 sf.localVars[slot] = value;